﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using War3Trainer.WindowsApi; // 你之前的封装

public class MemoryScanner
{
    [StructLayout(LayoutKind.Sequential)]
    public struct MEMORY_BASIC_INFORMATION
    {
        public IntPtr BaseAddress;
        public IntPtr AllocationBase;
        public uint AllocationProtect;
        public IntPtr RegionSize;
        public uint State;
        public uint Protect;
        public uint Type;
    }

    [DllImport("kernel32.dll")]
    static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);

    public static List<IntPtr> ScanProcessForString(int processId, string searchString)
    {
        List<IntPtr> foundAddresses = new List<IntPtr>();
        IntPtr hProcess = IntPtr.Zero;

        try
        {
            using (var pm = new War3Trainer.WindowsApi.ProcessMemory(processId))
            {
                // 获取模块范围，比如某个模块的范围，示例这里用整个进程地址空间
                // 实际应用中可限定在特定模块范围
                IntPtr address = IntPtr.Zero;
                IntPtr maxAddress = (IntPtr)0x7FFFFFFF; // 32位最大地址（可调整）

                while ((long)address < (long)maxAddress)
                {
                    MEMORY_BASIC_INFORMATION mbi;
                    int result = VirtualQueryEx(hProcess, address, out mbi, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)));
                    if (result == 0)
                    {
                        break; // 查询失败
                    }

                    // 判断区域是否可读
                    bool isReadable = (mbi.Protect & 0x04) != 0 || (mbi.Protect & 0x02) != 0 || (mbi.Protect & 0x20) != 0 || (mbi.Protect & 0x40) != 0 || (mbi.Protect & 0x80) != 0;

                    if (mbi.State == 0x1000 && isReadable) // MEM_COMMIT = 0x1000
                    {
                        try
                        {
                            byte[] buffer = pm.ReadBytes(mbi.BaseAddress, (int)mbi.RegionSize, out int bytesRead);
                            string bufStr = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                            int idx = 0;
                            while ((idx = bufStr.IndexOf(searchString, idx)) != -1)
                            {
                                IntPtr addrFound = IntPtr.Add(mbi.BaseAddress, idx);
                                foundAddresses.Add(addrFound);
                                Console.WriteLine($"addrFound=====>{addrFound}");
                                idx += searchString.Length;
                            }
                        }
                        catch
                        {
                            // 读取失败的区域跳过
                        }
                    }

                    // 移动到下一个区域
                    address = IntPtr.Add(mbi.BaseAddress, (int)mbi.RegionSize);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("扫描出错：" + ex.Message);
        }

        return foundAddresses;
    }
}
